var Util = require("../util/util.js")
var querystring = require("querystring");
var App = require("../common/App.js");
var Common = require("../service/Common.js");
var fs = require("fs");
var request = require("request");
var cheerio = require("cheerio");
var url = require("url");
var Q = require("q");
var zlib = require("zlib");
var SearchUrlService = require("./SearchUrlService.js");
var searchUrlService = new SearchUrlService();
var McryptService = require("./McryptService.js")
var mcryptService = new McryptService();


module.exports = SearchBase

function SearchBase(req,res){
    this.req = req;
    this.res = res;
}

SearchBase.prototype.initVar = function(){
    try{
        this.vvtoolPathValue = "";
        this.rootpath = App.runtime.expressApp.get("rootpath");
    	this.actionUrl = "/"+App.config.searchPath; //更改表单的action
        this.searchPathArg = "__vvtool_path_";//保存表单原来的action
        this.query = this.req.query;
        this.searchindex = "";
        this.proxyA = {};//this.actionUrl = "/"+App.config.searchPath; //更改表单的action
        this.proxyB = {};//
        this.proxy = {};//最后使用的代理
        this.optionAError = false;
        this.optionBError = false;
        this.hasTimeout = false;
        this.hasRes = false;//用两个代理，如果其中一个代理已经响应，另外一个则结束

        this.versionInfo = {};
        this.versionId = 0;
        this.denyKeywod = ['ip','ip地址','本地IP','本地IP'];
        this.searchUrl = "";
    }catch (err){
        console.log(err);
    }
}

SearchBase.prototype.init = function(){
    this.initVar();
    var c_version = App.config.c_version;

    //输入url
    if(this.req.query.url!=undefined){
        var urlParse = url.parse(this.req.query.url);
        var query = "";
        if(urlParse.hash!=undefined){
            query = urlParse.hash.toString().trim().substring(1);
        }
        if(urlParse.query!=undefined){
            if(query!=""){
                query = query+"&"+urlParse.query;
            }else{
                query = urlParse.query;
            }
        }

        if(query!=undefined){
            var hashQuery =  querystring.parse(query);
            for(var i in hashQuery){
                this.req.query[i] = hashQuery[i];
            }
        }

        var urlObj = {};
        urlObj.protocol = urlParse.protocol;
        urlObj.slashes = urlParse.slashes;
        urlObj.host = urlParse.host;
        urlObj.port = urlParse.port;
        urlObj.hostname = urlParse.hostname;
        urlObj.pathname = urlParse.pathname;

        if(urlParse.hostname=="www.baidu.com"){
            this.req.query[this.searchPathArg] = "http://www.baidu.com/s";
        }else{
            this.req.query[this.searchPathArg] = url.format(urlObj);
        }
        for(var i in c_version){
            var searchindex = c_version[i].searchindex
            if(searchindex.lastIndexOf(urlParse.hostname)>0){
                this.req.query['versionid'] = c_version[i].id;
                this.versionId = c_version[i].id;
                this.versionInfo = c_version[i];
                break;
            }
        }
        delete this.req.query.url;
    }

    //console.log(this.searchPathArg)
    //console.log(this.req.query);
    if(this.req.query[this.searchPathArg]!=undefined){
        var urlParse = url.parse(this.req.query[this.searchPathArg]);
        var hostname = urlParse.hostname;
        for(var i in c_version){
            var searchindex = c_version[i].searchindex;
            if(searchindex.lastIndexOf(hostname)>0){
                this.req.query['versionid'] = c_version[i].id;
                this.versionId = c_version[i].id;
                this.versionInfo = c_version[i];
                break;
            }
        }
    }

    if(this.versionInfo.id == undefined){
        this.res.redirect(301, "/i");
        return false;
    }
    this.searchindex = this.versionInfo.searchindex;

    var use_url = this.req.cookies.use_url;
    if(use_url==undefined || use_url==""){
        use_url = "";
    }else{
        use_url = use_url+"#";
    }
    var urlArr = use_url.split("#");
    if(urlArr.lastIndexOf(this.searchindex)<0){
        var uid = mcryptService.decode(this.req.cookies.uidCrypt);
        searchUrlService.saveUrl(uid,this.searchindex);

        this.res.setHeader( "Set-Cookie",["use_url="+use_url+this.searchindex] );
    }
}

/**
 *
 * 判断是否包含禁止的搜索词
 */
SearchBase.prototype.isDeny = function(){
    var isdeny = false;
    var len = this.denyKeywod.length;
    var keyword = this.keyword();
    for(var i=0;i<len;i++){
        if(keyword==this.denyKeywod[i]){
            isdeny = true;
            break;
        }
    }
    if(keyword.toLowerCase().indexOf("ip")>=0){
        isdeny = true;
    }
    return isdeny;
}

SearchBase.prototype.search = function(){
    var that = this;
    that.init();
    //try{
	that.res.setHeader("Content-type","text/html");
        if(this.keyword()!="" && !this.isDeny()){
            this.getProxy().then(
                function(){
                    return that.getProxyAndExclude(that.proxyA);
                },
                function(e){
                    throw e
                }
            ).then(
                function(){
                    if(that.proxyA.host!=undefined){
                        return true;
                    }
                },
                function(e){
                    if(that.proxyA.host!=undefined){
                        return true;
                    }else{
                        throw e;
                    }
                }
            ).then(
                function(){
                    that._search();
                },
                function(e){
                    that.timeout();
                }
            )
            ;
        }else{
            that._search();
        }
//    }catch (e){
//        console.log(e);
//	    that._contentIsRight();
//    }
}

SearchBase.prototype._search = function(){
	var that = this;
    var options = {
        host:'localhost',
        port:'808',
        method:'GET',
        path:'http://www.baidu.com/s?wd=%E7%A5%9B%E6%96%91&rsv_bp=0&ch=&tn=baidu&bar=&rsv_spt=3&ie=utf-8&rsv_sug3=6&rsv_sug4=282&rsv_sug1=8&rsv_sug2=0&inputT=0',
        headers:{
            'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
            'Accept-Charset':'GBK,utf-8;q=0.7,*;q=0.3',
            'Accept-Encoding':'gzip',
            'Accept-Language':'zh-CN,zh;q=0.8',
            'Cache-Control':'max-age=0',
            'Connection':'keep-alive',
            //'Host':'www.baidu.com',
			'Host':'localhost',
            //'Cookie':'Hm_lvt_9f14aaa038bbba8b12ec2a4a3e51d254=1390576441; BAIDUID=71B9D69368742E6167B1FA1752F6F049:FG=1; BDUSS=3RtdGtyY21wTmJvR0xHM1dPWmY2amJiaFRwcUVseH5CRHl-Y25WMUtoaThGaHRUQVFBQUFBJCQAAAAAAAAAAAEAAACeCrk~AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALyJ81K8ifNSb; locale=zh; BDRCVFR[YJmUnPTMq2R]=mk3SLVN4HKm; BD_CK_SAM=1; H_PS_PSSID=1458',
            //'If-Modified-Since':'Mon, 02 Apr 2012 18:24:28 GMT',
            'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36'
        }
    };
	options.path = this.getSearchReqUrl();
    this.searchUrl = options.path;
    var browserid = Common.getBrowserid(that.req,that.res);
    try{
        if(browserid>0){
            options.headers['User-Agent'] = App.config.c_browser[browserid]["agent"];
        }else{
            options.headers['User-Agent'] =  that.req.headers['user-agent'];
        }

    }catch (e){
    }

	var urlParse = url.parse(options.path);

    var optionsA = Util.clone(options);
    var optionsB = Util.clone(options);

	if(this.keyword()=="" || this.isDeny()){
        this.searchUrl = this.searchindex;
        optionsA.host = urlParse.host;
        optionsA.port = 80;
        optionsA.path = "/";
        optionsA.headers.Host = urlParse.host;
	}else{
        optionsA.host = that.proxyA.host;
        optionsA.headers.Host = urlParse.host;
        optionsA.port = that.proxyA.port;

        if(that.proxyB && that.proxyB.host!=undefined){
            optionsB.host = that.proxyB.host;
            optionsB.headers.Host = urlParse.host;
            optionsB.port = that.proxyB.port;
        }
	}
console.log(optionsA);
    //以下是接受数据的代码
    var reqA = http.request(optionsA, function(response) {
        var res = response;
        var data = "";
        switch (response.headers['content-encoding']) {
            case 'gzip':
                var res = zlib.createGunzip();
                response.pipe(res);
                break;
        }
        that._searchRes(res,that.proxyA);
    }).on('error', function(e) {
        that.failProxy(that.proxyA);
		that.timeout();
    });

    reqA.setTimeout(App.config.timeout.search, function(){
        reqA.abort();
    });
    reqA.end();


    if(that.proxyB.host!=undefined){
        var reqB = http.request(optionsB, function(response) {
            var res = response;
            var data = "";
            switch (response.headers['content-encoding']) {
                case 'gzip':
                    var res = zlib.createGunzip();
                    response.pipe(res);
                    break;
            }
            that._searchRes(res,that.proxyB);
        }).on('error', function(e) {
            that.failProxy(that.proxyB);
            that.timeout();
        });

        reqB.setTimeout(App.config.timeout.search, function(){
            reqB.abort();
        });
        reqB.end();
    }
}

SearchBase.prototype._searchRes = function(res,proxy){
    var that = this;
    if(that.hasRes){
        try{
            res.end();
        }catch (e){}
        return false;
    }
    that.proxy = proxy;//两个代理被挑选中的最优的一个
    that.hasRes = true;
    var startFetures = ['<','<f','<fo','<for'];
    var stopFetures = ['<','</','</f','</fo','</for','<form'];

    var formStart = false;
    var formEnd = false;
    var firstData = true;
    var bufferHtml = "";
    var html = "";

    res.setEncoding('utf8');
    res.on("end",function(){
	that._contentIsRight();
        that.end();
    })

    res.on("data",function(data){
        if(firstData){
            that.echo('<iframe style="display: none" src="/searchinfo?keyword='+that.keyword()+'"></iframe>');
            firstData = false;
        }
        bufferHtml = bufferHtml + data.toString();
        //console.log(bufferHtml,"@@@@@@@@@\n\n");

        //表单开始
        var formStartPos = bufferHtml.indexOf("<form");
        if(  formStartPos>=0 && !formStart){
            html = bufferHtml.substr(0,formStartPos);
            bufferHtml = bufferHtml.substr(formStartPos);
            formStart=true;
        }

        if(html!=""){
            that.echo(html);
            html="";
        }

        //表单结束
        var formStopPos = bufferHtml.indexOf("</form>");
        if( formStopPos>=0 && formStart){
            //console.log(bufferHtml,"\n\n\n");
            html = bufferHtml.substr(formStopPos+7);
            bufferHtml = bufferHtml.substr(0,formStopPos+7);

            //console.log(bufferHtml);
            bufferHtml = that.replaceForm(bufferHtml);

            formStart = false
            that.echo(bufferHtml);
            bufferHtml = "";

            //两个表单相靠近时,在另外一个表单结束后，需要判断第二个表单是否刚开始
            bufferHtml2 = html;
            var formStartPos = bufferHtml2.indexOf("<form");
            if(  formStartPos>=0 && !formStart){
                html = bufferHtml2.substr(0,formStartPos);
                bufferHtml = bufferHtml2.substr(formStartPos);
                formStart=true;
            }
        }

        if(html!=""){
            that.echo(html);
            html="";
        }

        //有表单开头特征
        if(formStart==false && bufferHtml!=""){
            var isFetures = false;
            for(var i=0;i<startFetures.length;i++){
                var fetures = startFetures[i];
                if(bufferHtml.lastIndexOf(fetures) + fetures.length == bufferHtml.length){
                        isFetures = true;
                        break;
                }
            }
            if(!isFetures){
                that.echo(bufferHtml);
                bufferHtml = "";
            }
        }

        //有表单结束特征
        if(formStart==true && bufferHtml!=""){
            var isFetures = false;
            for(var i=0;i<stopFetures.length;i++){
                var fetures = stopFetures[i];
                if(bufferHtml.indexOf(fetures) == 0){
                        isFetures = true;
                        break;
                }
            }

            if(!isFetures){
                that.echo(bufferHtml);
                bufferHtml = "";
            }
        }
    })
}

SearchBase.prototype._contentIsRight = function(){
	var that = this;
	//如果获取的内容不完整，则重试
	var isError = false;
    if(that.body && typeof that.body=="string"){
        if(that.body.indexOf("</html>")<0){
            isError = true;
        }
        //判断是否有某些特有的字符串


        var feature = that.versionInfo.feature;
        if(feature!=undefined){
            var hasFeature = false;
            for(var i=0;i<feature.length;i++){
                var f = feature[i];
                if(that.body.indexOf(f)>=0){
                    hasFeature = true;
                }
            }
            if(!hasFeature){
                isError = true;
            }
        }else{
            isError = true;
        }

    }else{
        isError=true;
	}
    if(isError ){
        var times = 1;
        if(!isNaN(Number(that.req.query.t)) ){
            times = Number(that.req.query.t)+1;
        }
        var query = Util.clone(that.req.query);
        query.t = times;
        var url  = that.req.path + "?" + querystring.stringify(query);

        if(times<3){
            that.echo("'>\"><script>window.location.href = '"+url+"'</script>");
        }

        that.failProxy(that.proxy);
    }
}


SearchBase.prototype.replaceForm = function(formHtml){
    var that = this;
	var $ = cheerio.load(formHtml);
    $("form").each(function(i,elem){
        //console.log(elem);
        var action = $(this).attr("action");
        var realAction = that.realAction(action);

        $(this).attr("action",that.actionUrl);

        var input = "<input type='hidden' name='regionid' value='"+Common.getRegionid(that.req,that.res)+"'/>"+
            "<input type='hidden' name='browserid' value='"+Common.getBrowserid(that.req,that.res)+"'/>"+
            "<input type='hidden' name='deviceid' value='"+Common.getDeviceid(that.req,that.res)+"'/>";
        $(elem).append(input);
        $(elem).append("<input type='hidden' name='"+that.searchPathArg+"' value='"+realAction+"'/>");
        that.vvtoolPathValue = realAction;
    });

    var html = $.html();
	return html;
	
}


SearchBase.prototype.realAction = function(action){
	if(typeof action!='string'){
		return '';
	}
    var urlParse = url.parse(action);
	var searchindex = this.searchindex;
    if(urlParse.host==null){
        var pos = searchindex.lastIndexOf("/");

        if(pos == searchindex.length-1){
            searchindex = searchindex.substr(0,pos);
        }
        action = searchindex+action;
    }
	return action;
}


SearchBase.prototype.getProxy = function(){
	var that = this;
    var deferred = Q.defer();
	var url = App.config.region.getproxy_url;
	url = url.replace('{regionId}',Common.getRegionid(this.req,this.res));

	request.get(url,function(err,res,body){
		if(!err && res.statusCode==200){
			try{
				var proxy = JSON.parse(body);
				that.proxyA = proxy;
				deferred.resolve(proxy);
			}catch(e){
				deferred.reject(e);
			}
		}else{
			deferred.reject(err);
		}
	})
	
	return deferred.promise;
}

SearchBase.prototype.getProxyAndExclude = function(excludeProxy){
    var that = this;
    var deferred = Q.defer();
    try{
        if(excludeProxy.host){
            excludeProxy = JSON.stringify(excludeProxy);
        }
    }catch (e){
        deferred.reject(e);
        return deferred.prmise;
    }

    var url = App.config.region.getproxy_and_exclude_url;
    url = url.replace('{regionId}',Common.getRegionid(this.req,this.res));
    url = url.replace('{proxy}',excludeProxy);

    request.get(url,function(err,res,body){
        if(!err && res.statusCode==200){
            try{
                var proxy = JSON.parse(body);
                that.proxyB = proxy;
                deferred.resolve(proxy);
            }catch(e){
                deferred.reject(e);
            }
        }else{
            deferred.reject(err);
        }
    })
    return deferred.promise;
}

SearchBase.prototype.relaseProxy = function(proxy){
	var url = App.config.region.release_proxy_url;
	try{
        if(this.proxyA.useid!=undefined){
            var urlA = url;
            urlA = urlA.replace('{userid}',this.proxyA.useid);
            request.get(urlA);
        }

        if(this.proxyB.useid!=undefined){
            var urlB = url;
            urlB = urlB.replace('{userid}',this.proxyB.useid);
            request.get(urlB);
        }
	}catch(e){}
}


SearchBase.prototype.echo=function(html){
	this.body = this.body+html;
	this.res.write(html);
}

SearchBase.prototype.end=function(){
    var that = this;
	this.relaseProxy();
    var output = App.config.ad.dianxin+App.config.tongji.normal;
    this.res.render("preview",function(error,html){
        if(error==null){
            html = html+"<script>loadHtmlEnd('"+that.searchEngineInfo.pagesel+"','"+that.searchPathArg+"','"+that.vvtoolPathValue+"')</script>";
            output = html+output;
        }
        output += "<script>parent.searchEnd('"+that.searchUrl+"')</script>";
        that.res.end(output);
    });
}

SearchBase.prototype.failProxy = function(proxy){
    //给代理标志一次失败的降级
    if(proxy.host!=undefined){
        var url = App.config.region.fail_proxy_url;
        url = url.replace('{proxy}',JSON.stringify(proxy));
        request.get(url,function(err,res,body){

        })
    }
}

/**
 * 超时
 * @returns {boolean}
 */
SearchBase.prototype.timeout = function(){
    var that = this;
    if(this.hasRes){
        return true;
    }
    if(this.hasTimeout){
        return true;
    }
    this.hasTimeout = true;

    var query = {};
    //query.refresh = 1;
    query.keyword = this.keyword();
    query.browserid = Common.getBrowserid(this.req,this.res);
    query.deviceid = Common.getDeviceid(this.req,this.res);
    query.regionid = Common.getRegionid(this.req,this.res);
    query.url = this.getSearchReqUrl();
    query.random =  Math.random();

    var times = 1;
    if(!isNaN(Number(that.req.query.t)) ){
        times = Number(that.req.query.t)+1;
    }
    var url = this.actionUrl+"?"+querystring.stringify(query);

    query.t =  times;
    var autoRetryUrl = this.actionUrl+"?"+querystring.stringify(query);

    this.res.render("timeout",
        {
            url:url,
            autoRetryUrl:autoRetryUrl,
            retryTimes:times,
            keyword:query.keyword,
            actionUrl:this.actionUrl,
            tongji:App.config.tongji.timeout
        });
	//this.res.end("超时");
}


/**
 * 获取搜索词
 * @returns {*}
 */
SearchBase.prototype.keyword = function(){
    var argsArr = this.versionInfo.searchargs.split(",");
    var len = argsArr.length;
    for(var i=0;i<len;i++){
        var arg = argsArr[i];
        if(this.query[arg]!=undefined && this.query[arg]!=""){
            return this.query[arg];
        }
    }

    return "";
}

SearchBase.prototype.getSearchReqUrl = function(){
    return this._getSearchReqUrl();
}
/**
 * 组装搜索url
 */
SearchBase.prototype._getSearchReqUrl = function(){
    var query = Util.clone(this.query),
        path  = query[this.searchPathArg];
    delete query[this.searchPathArg];
    var link = "";
    if(path.indexOf("?") > 0){//判断url中是否包括了字符 ?
        if( path.lastIndexOf("?")!=path.length-1){//如果url最后一个字符是 ?
            link = '&';
        }
    }else{
        link = '?';
    }

    var selfDefined = ['browserid','regionid','deviceid','versionid','t','random'];
    for(var i=0;i<selfDefined.length;i++){
        delete query[selfDefined[i]];
    }
    requrl = path + link + querystring.stringify(query);
    return requrl;
}
